#ifndef CHARTVIEW_H
#define CHARTVIEW_H

#include <QChartView>
#include <QtCharts/QCandlestickSeries>
#include <QDateTimeAxis>
#include <QDateTime>
#include <QValueAxis>
#include <QRubberBand>
class ChartView : public QChartView
{
public:
    ChartView(QChart* chart, QCandlestickSeries* series, QWidget* parent = nullptr)
        : QChartView(chart, parent), m_series(series), m_rubberBand(nullptr), m_isPanning(false) {
        setMouseTracking(true);
        setRubberBand(QChartView::NoRubberBand);
        m_hasInitialRange = false;
        m_minSpanX = 1e-3;
        m_minSpanY = 1e-6;

        // 尝试读取初始轴范围（如果已经设置）
        auto hAxes = chart->axes(Qt::Horizontal);
        auto vAxes = chart->axes(Qt::Vertical);
        if (!hAxes.isEmpty() && !vAxes.isEmpty()) {
            QAbstractAxis* h = hAxes.first();
            QAbstractAxis* v = vAxes.first();
            if (auto dt = qobject_cast<QDateTimeAxis*>(h)) {
                m_initXMin = dt->min().toMSecsSinceEpoch();
                m_initXMax = dt->max().toMSecsSinceEpoch();
            } else if (auto va = qobject_cast<QValueAxis*>(h)) {
                m_initXMin = va->min();
                m_initXMax = va->max();
            }

            if (auto va2 = qobject_cast<QValueAxis*>(v)) {
                m_initYMin = va2->min();
                m_initYMax = va2->max();
            } else if (auto dt2 = qobject_cast<QDateTimeAxis*>(v)) {
                m_initYMin = dt2->min().toMSecsSinceEpoch();
                m_initYMax = dt2->max().toMSecsSinceEpoch();
            }
            m_hasInitialRange = true;
        }
    }

protected:
    void mousePressEvent(QMouseEvent* event) override {
        if (event->button() == Qt::LeftButton) {
            if (!m_rubberBand) m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
            m_rubberOrigin = event->pos();
            m_rubberBand->setGeometry(QRect(m_rubberOrigin, QSize()));
            m_rubberBand->show();
        } else if (event->button() == Qt::MiddleButton || event->button() == Qt::RightButton) {
            m_isPanning = true;
            m_lastPanPoint = event->pos();
            setCursor(Qt::ClosedHandCursor);
        }
        QChartView::mousePressEvent(event);
    }

    void mouseMoveEvent(QMouseEvent* event) override {
        if (m_rubberBand && m_rubberBand->isVisible()) {
            m_rubberBand->setGeometry(QRect(m_rubberOrigin, event->pos()).normalized());
        } else if (m_isPanning) {
            QPoint delta = event->pos() - m_lastPanPoint;
            panChart(delta.x(), delta.y());
            m_lastPanPoint = event->pos();
        }
        QChartView::mouseMoveEvent(event);
    }

    void mouseReleaseEvent(QMouseEvent* event) override {
        if (event->button() == Qt::LeftButton && m_rubberBand && m_rubberBand->isVisible()) {
            QRect rect = m_rubberBand->geometry();
            m_rubberBand->hide();

            if (rect.width() > 10 && rect.height() > 10) {
                // 将像素坐标映射到图表数据坐标
                QPointF topLeft = chart()->mapToValue(QPointF(rect.left(), rect.top()), m_series);
                QPointF bottomRight = chart()->mapToValue(QPointF(rect.right(), rect.bottom()), m_series);

                double minX = qMin(topLeft.x(), bottomRight.x());
                double maxX = qMax(topLeft.x(), bottomRight.x());
                double minY = qMin(topLeft.y(), bottomRight.y());
                double maxY = qMax(topLeft.y(), bottomRight.y());

                // 设置坐标轴范围（支持 QDateTimeAxis 和 QValueAxis）
                auto hAxes = chart()->axes(Qt::Horizontal);
                auto vAxes = chart()->axes(Qt::Vertical);
                if (!hAxes.isEmpty()) setAxisRange(hAxes.first(), minX, maxX, true);
                if (!vAxes.isEmpty()) setAxisRange(vAxes.first(), minY, maxY, false);
            }
        } else if ((event->button() == Qt::MiddleButton || event->button() == Qt::RightButton) && m_isPanning) {
            m_isPanning = false;
            setCursor(Qt::ArrowCursor);
        }
        QChartView::mouseReleaseEvent(event);
    }

    void mouseDoubleClickEvent(QMouseEvent* event) override {
        // 双击重置到初始范围（如果有）
        if (m_hasInitialRange) {
            auto hAxes = chart()->axes(Qt::Horizontal);
            auto vAxes = chart()->axes(Qt::Vertical);
            if (!hAxes.isEmpty()) setAxisRange(hAxes.first(), m_initXMin, m_initXMax, true);
            if (!vAxes.isEmpty()) setAxisRange(vAxes.first(), m_initYMin, m_initYMax, false);
        }
        QChartView::mouseDoubleClickEvent(event);
    }

    void wheelEvent(QWheelEvent* event) override {
        // 鼠标滚轮在鼠标位置缩放
        const double factor = (event->angleDelta().y() > 0) ? 0.8 : 1.25;
        zoomAt(event->position().toPoint(), factor);
        QChartView::wheelEvent(event);
    }

private:
    void setAxisRange(QAbstractAxis* axis, double minV, double maxV, bool isHorizontal) {
        if (!axis) return;
        if (auto dt = qobject_cast<QDateTimeAxis*>(axis)) {
            QDateTime a = QDateTime::fromMSecsSinceEpoch((qint64)minV);
            QDateTime b = QDateTime::fromMSecsSinceEpoch((qint64)maxV);
            dt->setRange(a, b);
        } else if (auto va = qobject_cast<QValueAxis*>(axis)) {
            va->setRange(minV, maxV);
        } else {
            // fallback if custom axis
        }
    }

    void panChart(int dx, int dy) {
        // 将像素位移转换为坐标轴位移
        QRectF plotArea = chart()->plotArea();
        if (plotArea.width() <= 0 || plotArea.height() <= 0) return;

        auto hAxes = chart()->axes(Qt::Horizontal);
        auto vAxes = chart()->axes(Qt::Vertical);
        if (hAxes.isEmpty() || vAxes.isEmpty()) return;

        QAbstractAxis* h = hAxes.first();
        QAbstractAxis* v = vAxes.first();

        double xMin = 0, xMax = 0, yMin = 0, yMax = 0;
        bool hIsDate = false;
        if (auto dt = qobject_cast<QDateTimeAxis*>(h)) {
            hIsDate = true;
            xMin = dt->min().toMSecsSinceEpoch();
            xMax = dt->max().toMSecsSinceEpoch();
        } else if (auto va = qobject_cast<QValueAxis*>(h)) {
            xMin = va->min();
            xMax = va->max();
        }

        if (auto va2 = qobject_cast<QValueAxis*>(v)) {
            yMin = va2->min();
            yMax = va2->max();
        } else if (auto dt2 = qobject_cast<QDateTimeAxis*>(v)) {
            yMin = dt2->min().toMSecsSinceEpoch();
            yMax = dt2->max().toMSecsSinceEpoch();
        }

        double xRange = xMax - xMin;
        double yRange = yMax - yMin;
        if (xRange <= 0 || yRange <= 0) return;

        double dxVal = - (double)dx / plotArea.width() * xRange;
        double dyVal = (double)dy / plotArea.height() * yRange; // 鼠标向下增加 y

        double newMinX = xMin + dxVal;
        double newMaxX = xMax + dxVal;
        double newMinY = yMin + dyVal;
        double newMaxY = yMax + dyVal;

        setAxisRange(h, newMinX, newMaxX, true);
        setAxisRange(v, newMinY, newMaxY, false);
    }

    void zoomAt(const QPoint& mousePos, double factor) {
        if (!chart()) return;
        // 将鼠标位置映射到数据坐标
        QPointF valueAtMouse = chart()->mapToValue(QPointF(mousePos), m_series);

        auto hAxes = chart()->axes(Qt::Horizontal);
        auto vAxes = chart()->axes(Qt::Vertical);
        if (hAxes.isEmpty() || vAxes.isEmpty()) return;

        QAbstractAxis* h = hAxes.first();
        QAbstractAxis* v = vAxes.first();

        double xMin = 0, xMax = 0, yMin = 0, yMax = 0;
        if (auto dt = qobject_cast<QDateTimeAxis*>(h)) {
            xMin = dt->min().toMSecsSinceEpoch();
            xMax = dt->max().toMSecsSinceEpoch();
        } else if (auto va = qobject_cast<QValueAxis*>(h)) {
            xMin = va->min();
            xMax = va->max();
        }

        if (auto va2 = qobject_cast<QValueAxis*>(v)) {
            yMin = va2->min();
            yMax = va2->max();
        } else if (auto dt2 = qobject_cast<QDateTimeAxis*>(v)) {
            yMin = dt2->min().toMSecsSinceEpoch();
            yMax = dt2->max().toMSecsSinceEpoch();
        }

        double newMinX = valueAtMouse.x() + (xMin - valueAtMouse.x()) * factor;
        double newMaxX = valueAtMouse.x() + (xMax - valueAtMouse.x()) * factor;
        double newMinY = valueAtMouse.y() + (yMin - valueAtMouse.y()) * factor;
        double newMaxY = valueAtMouse.y() + (yMax - valueAtMouse.y()) * factor;

        // 限制最小跨度，避免过度放大
        if (qAbs(newMaxX - newMinX) < m_minSpanX) {
            double centerX = (newMaxX + newMinX) / 2.0;
            newMinX = centerX - m_minSpanX / 2.0;
            newMaxX = centerX + m_minSpanX / 2.0;
        }
        if (qAbs(newMaxY - newMinY) < m_minSpanY) {
            double centerY = (newMaxY + newMinY) / 2.0;
            newMinY = centerY - m_minSpanY / 2.0;
            newMaxY = centerY + m_minSpanY / 2.0;
        }

        setAxisRange(h, newMinX, newMaxX, true);
        setAxisRange(v, newMinY, newMaxY, false);
    }

private:
    QCandlestickSeries* m_series;
    QRubberBand* m_rubberBand;
    QPoint m_rubberOrigin;
    bool m_isPanning;
    QPoint m_lastPanPoint;
    // 初始轴范围，用于双击重置
    bool m_hasInitialRange;
    double m_initXMin;
    double m_initXMax;
    double m_initYMin;
    double m_initYMax;
    double m_minSpanX;
    double m_minSpanY;
};

#endif // CHARTVIEW_H
